(Zhu et al. 2008) (Xie 2023) (Robinson, McCarthy, and Smyth 2010) (Morgan 2022) (Durinck et al. 2009) (Gu et al. 2014) (Gu, Eils, and Schlesner 2016) (Wickham 2016) (Slowikowski 2023) (Raudvere et al. 2019)

if (!requireNamespace("GEOmetadb", quietly = TRUE))
  BiocManager::install("GEOmetadb")

if (!requireNamespace("knitr", quietly = TRUE))
  install.packages("knitr")

if (!require("edgeR", quietly = TRUE))
  BiocManager::install("edgeR")

if (!requireNamespace("BiocManager", quietly = TRUE))
  install.packages("BiocManager")

if (!requireNamespace("biomaRt", quietly = TRUE))
  BiocManager::install("biomaRt")

if (!requireNamespace("ComplexHeatmap", quietly = TRUE))
  BiocManager::install("ComplexHeatmap")

if (!requireNamespace("circlize", quietly = TRUE))
  BiocManager::install("circlize")

if (!requireNamespace("ggplot2", quietly = TRUE))
  install.packages("ggplot2")

if (!requireNamespace("ggrepel", quietly = TRUE))
  install.packages("ggrepel")

Calling required packages

library(BiocManager)
library(GEOmetadb)
library(knitr)
library(edgeR)
library(biomaRt)
library(ComplexHeatmap)
library(circlize)
library(ggplot2)
library(ggrepel)

Download the data

GSE152074 raw data supplementary file downloaded

sfiles = getGEOSuppFiles('GSE152075')
trying URL 'https://ftp.ncbi.nlm.nih.gov/geo/series/GSE152nnn/GSE152075/suppl//GSE152075_raw_counts_GEO.txt.gz?tool=geoquery'
Content type 'application/x-gzip' length 7121083 bytes (6.8 MB)
downloaded 6.8 MB
fnames = rownames(sfiles)
# there is only one supplemental file
readData = read.table(fnames[1],header=TRUE, check.names = TRUE)

Data

Data from (Lieberman et al. 2020).

kable(readData[1:5, 1:5], type = "html", row.names = TRUE)
POS_001 POS_002 POS_003 POS_004 POS_005
A1BG 0 1 0 0 18
A1CF 0 0 2 0 0
A2M 69 36 84 42 83
A2ML1 2 0 0 0 3
A2MP1 0 0 0 0 21

Table 1: Original data contains HGNC annotation as row names. Column names have prefixes before their identifier number as either POS or NEG. Corresponding to either positive for COVID19 or negative.

Assess

Add 1 to all values of data so later on when conducting log2(cpm) we can avoid negative infinity values. (Advised by Professor Isserlin)

readData <- readData + 1

Setting first column as gene id for future format purposes

#Place rownames in first column for future format purposes
inter <- data.frame("HUGO" = rownames(readData))
geneData <- cbind(inter$HUGO, readData)
colnames(geneData)[1] <- "HUGO"

Clean

Remove any outliers that does not have at least 2 read per million in n of the samples. We set this as 2 since we add 1 to all of our dataset in the beginning of the code to have better plots. Denoting n as the smallest group of replicates which is the control group of 53. Using n = 53 conduct the removal of low counts.

#translate out counts into counts per millison using 
#the edgeR package function cpm
cpms = cpm(geneData[,2:485])
rownames(cpms) <- geneData[,1]
# get rid of low counts
keep = rowSums(cpms >2) >=53
geneData_exp_filtered = geneData[keep,]

Remove version numbers if they exists on gene id(HUGO) column. This makes it easier for mapping later on.

geneData_exp_filtered[,1] <- gsub("\\.[0-9]", "", geneData_exp_filtered[,1])

Map

#Mapping the name using biomatr
# list available gene annotation databases
bio <- useMart("ensembl", dataset = "hsapiens_gene_ensembl")
conversion_stash <- "geneMapping.rds"
if(file.exists(conversion_stash)){
  geneMapping <- readRDS(conversion_stash)
} else{
# convert column of gene IDs to Hugo symbols
geneMapping <- getBM(attributes = c("ensembl_gene_id", "hgnc_symbol"),
                     mart = bio,
                     filters = "hgnc_symbol",
                     values = geneData_exp_filtered[,1])
saveRDS(geneMapping, conversion_stash)
}

Combine the mapped gene data to original data

#Merge the data
mergedData <- merge(geneData_exp_filtered, geneMapping, by.x = 1, by.y = 2)
#remove duplicate rows in the gene data
mergedDataNoDup <- mergedData[!duplicated(mergedData[,1:485]),]

Apply Normalization

Randomly sample data to reduce the size of sample. Original sample is too large leading to computation errors due to the limitation of author’s computer.


set.seed(12345)
randomSamplePOS <- sample(mergedDataNoDup[2:431], 25)
randomSampleNEG <- sample(mergedDataNoDup[432:485], 25)
randomSample <- cbind(randomSamplePOS,randomSampleNEG, mergedDataNoDup$ensembl_gene_id, mergedDataNoDup$HUGO)

Define groups to use in normalization


samples <- data.frame(lapply(colnames(randomSample[1:50]), 
        FUN=function(x){unlist(strsplit(x, 
                        split = "_"))[c(2,1)]}))
colnames(samples) <- colnames(randomSample[1:50])
rownames(samples) <- c("patients","cell_type")
samples <- data.frame(t(samples))

Applying TMM to data


filtered_data_matrix <- as.matrix(randomSample[1:50])
rownames(filtered_data_matrix) <- randomSample$`mergedDataNoDup$ensembl_gene_id`
d = DGEList(counts=filtered_data_matrix, group=samples$cell_type)

d = calcNormFactors(d)

normalized_counts <- cpm(d)
#add columns of ensembl and hgnc id

normalized_count_data = data.frame(normalized_counts)
normalized_count_data$ensembl_gene_id <- mergedDataNoDup$ensembl_gene_id
normalized_count_data$hgnc_symbol <- mergedDataNoDup$HUGO


#This is a duplicate ensembl id that is giving errors when running code.
normalized_count_data <- normalized_count_data[-c(1902),]
model_design <- model.matrix(~samples$cell_type+0)
d <- estimateDisp(d, model_design)

Differential Gene Expression

LIMMA

p-value calculation using LIMMA

model_design <- model.matrix(~ samples$cell_type )

expressionMatrix <- as.matrix(normalized_count_data[,1:50])
rownames(expressionMatrix) <- 
  normalized_count_data$ensembl_gene_id
colnames(expressionMatrix) <- 
  colnames(normalized_count_data)[1:50]
minimalSet <- ExpressionSet(assayData=expressionMatrix)

Taking into account Patient variability

model_design_pat <- model.matrix(
  ~ samples$patients + samples$cell_type)
fit_pat <- lmFit(minimalSet, model_design_pat)
fit2_pat <- eBayes(fit_pat,trend=TRUE)

topfit_pat <- topTable(fit2_pat, 
                   coef=ncol(model_design_pat),
                   adjust.method = "BH",
                   number = nrow(expressionMatrix))
#merge hgnc names to topfit table
output_hits_pat <- merge(normalized_count_data[,51:52],
                         topfit_pat,by.y=0,by.x=1,all.y=TRUE)
#sort by pvalue
output_hits_pat <- output_hits_pat[order(output_hits_pat$P.Value),]
length(which(output_hits_pat$P.Value < 0.05))
[1] 1325
length(which(output_hits_pat$adj.P.Val < 0.05))
[1] 0

QLF

d = DGEList(counts=filtered_data_matrix, group=samples$cell_type)
d <- estimateDisp(d, model_design_pat)
fit <- glmQLFit(d, model_design_pat)
qlf.pos_vs_neg <- glmQLFTest(fit, coef='samples$cell_typePOS')
kable(topTags(qlf.pos_vs_neg), type="html",row.names = FALSE)
logFC logCPM F PValue FDR
8.508844 3.630861 56.94465 0 0.00e+00
9.217790 3.372834 44.85154 0 2.00e-07
8.238509 3.548781 39.51653 0 1.60e-06
8.480522 3.438800 38.21139 0 2.40e-06
7.357389 3.446313 35.77654 0 6.60e-06
14.042290 8.460151 34.52607 0 9.50e-06
8.560409 2.932483 34.40267 0 9.50e-06
10.527753 7.518887 32.50111 0 2.20e-05
7.998298 3.187208 31.11275 0 3.99e-05
7.616290 3.501343 29.92408 0 6.62e-05
x
BH
x
samples$cell_typePOS
x
glm

P-values were corrected using Quasilikelihood method. Quasilikelihood is better becacuse it is tailored towards RNAseq data

qlf_output_hits <- topTags(qlf.pos_vs_neg,sort.by = "PValue",
                           n = nrow(normalized_count_data))
length(which(qlf_output_hits$table$PValue < 0.05))
[1] 1569
length(which(qlf_output_hits$table$FDR < 0.05))
[1] 276

Thresholded over-representation analysis

Write to file upregulated, and downregulated genes

Which ones are upregulated and downregulated

length(which(qlf_output_hits$table$PValue < 0.05 
             & qlf_output_hits$table$logFC > 0))
[1] 1424
length(which(qlf_output_hits$table$PValue < 0.05 
             & qlf_output_hits$table$logFC < 0))
[1] 145
qlf_output_hits_withgn <- merge(randomSample[,51:52],qlf_output_hits, by.x=1, by.y = 0)
#number higher the lower the pvalue, and if it is upregulated number is positive, and negative for downregulated
qlf_output_hits_withgn[,"rank"] <- -log(qlf_output_hits_withgn$PValue,base =10) * sign(qlf_output_hits_withgn$logFC)
qlf_output_hits_withgn <- qlf_output_hits_withgn[order(qlf_output_hits_withgn$rank),]
upregulated_genes <- qlf_output_hits_withgn$`mergedDataNoDup$HUGO`[
  which(qlf_output_hits_withgn$PValue < 0.05 
             & qlf_output_hits_withgn$logFC > 0)]
downregulated_genes <- qlf_output_hits_withgn$`mergedDataNoDup$HUGO`[
  which(qlf_output_hits_withgn$PValue < 0.05 
             & qlf_output_hits_withgn$logFC < 0)]
write.table(x=upregulated_genes,
            file=file.path("data","upregulated_genes.txt"),sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)
write.table(x=downregulated_genes,
            file=file.path("data","downregulated_genes.txt"),sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)
write.table(x=data.frame(genename= qlf_output_hits_withgn$`mergedDataNoDup$HUGO`,F_stat= qlf_output_hits_withgn$rank),
            file=file.path("data","ranked_genelist.txt"),sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)

Non-thresholded Gene set Enrichment Analysis

gmt_url = "http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/"
# list all the files on the server
filenames = RCurl::getURL(gmt_url)
tc = textConnection(filenames)
contents = readLines(tc)
close(tc)
# get the gmt that has all the pathways and does not include terms inferred
# from electronic annotations(IEA) start with gmt file that has pathways only
rx = gregexpr("(?<=<a href=\")(.*.GOBP_AllPathways_no_GO_iea.*.)(.gmt)(?=\">)", contents,
    perl = TRUE)
gmt_file = unlist(regmatches(contents, rx))
download.file(paste(gmt_url, gmt_file, sep = ""), "bader_lab.gmt")
trying URL 'http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/Human_GOBP_AllPathways_no_GO_iea_April_02_2023_symbol.gmt'
Content type 'unknown' length 8507005 bytes (8.1 MB)
downloaded 8.1 MB

Conduct non-thresholded gene set enrichment analysis using the ranked set of genes from Assignment #2.  

1. What method did you use? What genesets did you use? Make sure to specify versions and cite your methods.  

I used the GSEA desktop application to run GSEA (Mootha et al. 2003).
I used the genesets from the bader lab extracted from the code above I used. Or it can be retrieved from here http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/.

2. Summarize your enrichment results. 

SARs-CoV-2 positive samples:
4965 / 6074 gene sets are upregulated in phenotype na_pos
442 gene sets are significant at FDR < 25%
410 gene sets are significantly enriched at nominal pvalue < 1%
662 gene sets are significantly enriched at nominal pvalue < 5%
Top gene-set: HALLMARK_INTERFERON_ALPHA_RESPONSE%MSIGDBHALLMARK%HALLMARK_INTERFERON_ALPHA_RESPONSE
Number of genes in leading edge: 80
Top gene associated: CXCL11

SARs-CoV-2 negative samples:
1109 / 6074 gene sets are upregulated in phenotype na_neg
274 gene sets are significantly enriched at FDR < 25%
196 gene sets are significantly enriched at nominal pvalue < 1%
276 gene sets are significantly enriched at nominal pvalue < 5%
Top gene-set: ENERGY DERIVATION BY OXIDATION OF ORGANIC COMPOUNDS%GOBP%GO:0015980
Number of genes in leading edge: 165
Top gene associated: TEFM

3. How do these results compare to the results from the thresholded analysis in Assignment #2. Compare qualitatively. Is this a straight forward comparison? Why or why not?  

For the upregulated genes the top results are negative regulation of viral genome replication, negative regulation of viral process, response to type II interferon. downregulated we got cytoplasmic translation, positive regulation of respiratory burst, and intermediate filament-based process. For upregulated in thresholded and non-thresholded they align a bit together by having interferon related pathway results. Other then that they don’t seem to be similar. A common pathway in downregulated and and all of the genes for thresholded was a pathway related to cytoplasmic. However in non thresholded there were cytoplasmic related pathways but were very low in the list. It is not a straight forward comparison they both have different values as analysis. The thresholded could be more sensitive while the non-thresholded be more general.

Visualize your gene set Enrichment Analysis in Cytoscape  

1.  

Create an enrichment map - how many nodes and how many edges in the resulting map?  

379 Nodes
1511 Edges

What thresholds were used to create this map?

FDR q-value cutoff: 0.1
Analysis Type: GSEA
Node cutoff: 0.1
Edge cutoff: 0.375

Make sure to record all thresholds. Include a screenshot of your network prior to manual layout.  

Figure 0: Screenshot of network prior to manual layout

2. Annotate your network - what parameters did you use to annotate the network. If you are using the default parameters make sure to list them as well.

Used the auto annotate application in cytoscape.
Cluster algorithm: MCL Cluster
Label Column: GS_DESCR
Label Algorithm: WordCloud: Adjacent Words(default)
Max words per label: 3
Minimum word occurrence: 1
Adjacent word bonus: 8
Border Width: 3
Opacity: 20%
Font Scale: 20%

Figure 1: Annotated network

3. Make a publication ready figure - include this figure with proper legends in your notebook.

Figure 2: Collapsed

4. Collapse your network to a theme network. What are the major themes present in this analysis? Do they fit with the model? Are there any novel pathways or themes?  

Figure 3: Collapsed Major themes present:

Up-regulated:

  • GPCRS Rhodopsin ligand
  • Chemokine Migration chemotaxis
  • Cellular response necrosis
  • type II interferon
  • Migration monocyte chemotaxis
  • Surface receptor pattern

Down-regulated:

  • gluconeogenesis glycolysis
  • superpathway warburg effect
  • srp protein synthesis

Do they fit with the model?

There are major themes that coincide with the model present in the original paper. Such as the type II interferon, or surface receptor pattern is something that is common in COVID-19.

Novel pathways?
There exists some novel pathways in the network such as the foxo-mediated transcription of cell cycle gene. Pathways such as these there are not a lot of studies on them. Not just this one but out of the many pathways there are some novel interesting pathways to look at.

Interpretation and detailed view of results

The most important aspect of the analysis is relating your results back to the initial data and question.

1. Do the enrichment results support conclusions or mechanism discussed in the original paper? How do these results differ from the results you got from Assignment #2 thresholded methods.

This is a quotation taken from the original paper “SARS-CoV-2 induced a strong antiviral response with up-regulation of antiviral factors such as OAS1-3 and IFIT1-3 and T helper type 1 (Th1) chemokines CXCL9/10/11, as well as a reduction in transcription of ribosomal proteins” (Lieberman et al. 2020). They have found up-regulation in number of genes. The largest collapsed theme with 729 genes the GPCRS Rhodopsin ligand has two very large pathways named the GPCR ligand binding, and the CLASS A 1 (RHODOPSIN-LIKE RECEPTORS). Both of these gene-sets have at the top of their leading edge the CXCL 10/11/13 similar to the paper where they had up-regulation in the CXCL 9/10/11. In this sense the enrichment results support conclusions made in the original paper. Another example is the chemokine migration chemotaxis. In this major theme there are gene-sets involved in pathways such as the response to type II interferon, cellular response to type II interferon, . In the original paper they mention that as viral load increased the expression of interferon-responsive genes went up. Both of the two themes mentioned are up-regulated gene-sets. It seems that the enrichment results support the conclusion in the original paper.
Comparing from A2 threshold methods in the upregulated analysis using g:profiler we also had results such as response to type II interferon, and cellular response to type II interferon. This aligns with our GSEA results. The significant pathways seem to be aligning but the minor ones that have weak significance is where the major differences are betweeen t he Assignment 2 thresholded methods and Assignment 3.

For down regulated gene-sets for our network results from GSEA shows a major theme called srp protein synthesis. In this we have genesets such as the cytoplasmic translation. This gene-set is the largest gene-set inside srp protein synthesis and it is also the top result for down regulated genes gene-set for g:profiler using GO annotation.

Comparing the model in original paper, Assignment 2 results, and Assignment 3 results the significant pathways coincide but the less significant pathways is where the change occurs.

2. Can you find evidence, i.e. publications, to support some of the results that you see. How does this evidence support your result?

In a paper they state that SARS-CoV-2 infected thyroid gland activated the interferon pathways aligning with our results in the up-regulation (Poma et al. 2021). Another paper explains the down regulation of cytoplasmic translation. SARS-CoV-2 suppresses host protein translation leading to a down regulation of cytoplasmic translation pathways (Zhang et al. 2022). In both papers we can see supporting evidence for the results we got from the GSEA in upregulated and downregulated.

1. Add a post analysis to your main network using specific transcription factors, microRNAs or drugs. Include the reason why you chose the specific miRs, TFs or drugs (i.e publications indicating that they might be related to your model). What does this post analysis show?

Added a geneset for drugs from the bader lab. From this link (http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/DrugTargets/Human_DrugBank_all_symbol.gmt).

I chose drugs because COVID-19 as of 2023 has no exact cure for the disease since the virus is constantly evolving. However having drug targets, and drugs to treat COVID-19 could be a very effective way of defeating the virus if we can reduce the risks of severity in COVID-19.

Conducted a exploratory analysis, and known signature analysis.
The exploratory analysis showed me the significant genesets and these are the ones I chose to focus on.
Mann-Whitney(Two-sided): 0.05

The most significant drug targets were Artenimol, Anisomycin, (S)-3-Phenyllactic Acid, Puromycin, NADH.

Using the Overlap is X percent of Sig gs: largest overlap drug targets is NADH, Aripiprazole, Loxapine, Ziprasidone, Aripiprazole Lauroxil

Hypergeometric Test: 0.25 The best test values are NADH, Aripiprazole, Loxapine, Ziprasidone, CYT997

In all 3 analysis we see that NADH is existent. NADH is the reduced form of NAD+. In the drugbank system they say that NADH has been useful in treating Parikinson’s disease. NADH is a significant nutrient in other diseases but how about for COVID-19. Multiple papers shows that NAD+ deficiency might be one of the main causes of the disease severity in COVID-19 (Miller, Wentzel, and Richards 2020). This aligns with the significant gene sets that are seen in the cytoscape analysis.

Figure 4: Drug Targets The figure is too large so none of the nodes are actually visible in cytoscape unless zoomed in.  Since it is difficult to view in network view. Here are the table views and just a few drug targets zoomed in for the analysis done.  

Figure 5: Drug Targets zoomed in Mann-Whitney network

Figure 6: Drug Targets Mann-Whitney table view

Figure 7: Drug Targets zoomed in hypergeometric Figure 8: Drug Targets table hypergeometric

Figure 9: Drug Targets zoomed in overlap

Figure 10: Drug Targets table overlap

Compilation

This code compiles with docker as of 04/04/2023.

References

Durinck, Steffen, Paul T. Spellman, Ewan Birney, and Wolfgang Huber. 2009. “Mapping Identifiers for the Integration of Genomic Datasets with the r/Bioconductor Package biomaRt.” Nature Protocols 4: 1184–91.
Gu, Zuguang, Roland Eils, and Matthias Schlesner. 2016. “Complex Heatmaps Reveal Patterns and Correlations in Multidimensional Genomic Data.” Bioinformatics. https://doi.org/10.1093/bioinformatics/btw313.
Gu, Zuguang, Lei Gu, Roland Eils, Matthias Schlesner, and Benedikt Brors. 2014. “Circlize Implements and Enhances Circular Visualization in r.” Bioinformatics 30: 2811–12.
Lieberman, Nicole AP, Vikas Peddu, Hong Xie, Lasata Shrestha, Meei-Li Huang, Megan C Mears, Maria N Cajimat, et al. 2020. “In Vivo Antiviral Host Transcriptional Response to SARS-CoV-2 by Viral Load, Sex, and Age.” PLoS Biology 18 (9): e3000849.
Miller, R., A. R. Wentzel, and G. A. Richards. 2020. “COVID-19: NAD+ Deficiency May Predispose the Aged, Obese and Type2 Diabetics to Mortality Through Its Effect on SIRT1 Activity.” Medical Hypotheses 144: 110044. https://doi.org/https://doi.org/10.1016/j.mehy.2020.110044.
Mootha, VK, CM Lindgren, KF Eriksson, A Subramanian, S Sihag, J Lehar, P Puigserver, et al. 2003. “PGC-1α-Responsive Genes Involved in Oxidative Phosphorylation Are Coordinately Downregulated in Human Diabetes.” Nature Genetics 34 (3): 267–73. https://doi.org/10.1038/ng1180.
Morgan, Martin. 2022. BiocManager: Access the Bioconductor Project Package Repository. https://CRAN.R-project.org/package=BiocManager.
Poma, Anna Maria, Alessandro Basolo, Daniele Bonuccelli, Agnese Proietti, Elena Macerola, Clara Ugolini, Ludovica Torregrossa, et al. 2021. “Activation of Type i and Type II Interferon Signaling in SARS-CoV-2-Positive Thyroid Tissue of Patients Dying from COVID-19.” Thyroid : Official Journal of the American Thyroid Association 31 (12): 1766–75. https://doi.org/10.1089/thy.2021.0345.
Raudvere, Uku, Liis Kolberg, Ivan Kuzmin, Tambet Arak, Priit Adler, Hedi Peterson, and Jaak Vilo. 2019. “G:profiler: A Web Server for Functional Enrichment Analysis and Conversions of Gene Lists.” Nucleic Acids Research. https://doi.org/10.1093/nar/gkz369.
Robinson, Mark D, Davis J McCarthy, and Gordon K Smyth. 2010. “edgeR: A Bioconductor Package for Differential Expression Analysis of Digital Gene Expression Data.” Bioinformatics 26 (1): 139–40. https://doi.org/10.1093/bioinformatics/btp616.
Slowikowski, Kamil. 2023. Ggrepel: Automatically Position Non-Overlapping Text Labels with ’Ggplot2’. https://CRAN.R-project.org/package=ggrepel.
Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.
Xie, Yihui. 2023. Knitr: A General-Purpose Package for Dynamic Report Generation in r. https://yihui.org/knitr/.
Zhang, Dongdong, Longlong Zhu, Yu Wang, Pengfei Li, and Yu Gao. 2022. “Translational Control of COVID-19 and Its Therapeutic Implication.” Frontiers in Immunology 13: 857490. https://doi.org/10.3389/fimmu.2022.857490.
Zhu, Yuelin, Sean Davis, Robert Stephens, Paul S. Meltzer, and Yidong Chen. 2008. “GEOmetadb: Powerful Alternative Search Engine for the Gene Expression Omnibus.” Bioinformatics (Oxford, England) 24 (23): 2798–2800. https://doi.org/10.1093/bioinformatics/btn520.
LS0tDQp0aXRsZTogIkEzIg0KYXV0aG9yOiBKYWUgSHl1bmcgSnVuZw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnMicNCiAgICBkZl9wcmludDogcGFnZWQNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogMg0KYmlibGlvZ3JhcGh5OiAnQTMuYmliJw0KLS0tDQoNCg0KW0BnZW9tZXRhZGJdDQpbQGtuaXRyXQ0KW0BlZGdlcl0NCltAYmlvY21hbmFnZXJdDQpbQGJpb21hcnRdDQpbQGNpcmNsaXplXQ0KW0Bjb21wbGV4XQ0KW0BnZ3Bsb3QyXQ0KW0BnZ3JlcGVsXQ0KW0BncHJvZmlsZV0NCmBgYHtyLCBtZXNzYWdlPSBGQUxTRX0NCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiR0VPbWV0YWRiIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiR0VPbWV0YWRiIikNCg0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJrbml0ciIsIHF1aWV0bHkgPSBUUlVFKSkNCiAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KDQppZiAoIXJlcXVpcmUoImVkZ2VSIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiZWRnZVIiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBpbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpDQoNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiYmlvbWFSdCIsIHF1aWV0bHkgPSBUUlVFKSkNCiAgQmlvY01hbmFnZXI6Omluc3RhbGwoImJpb21hUnQiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkNvbXBsZXhIZWF0bWFwIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiQ29tcGxleEhlYXRtYXAiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImNpcmNsaXplIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2lyY2xpemUiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImdncGxvdDIiLCBxdWlldGx5ID0gVFJVRSkpDQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImdncmVwZWwiLCBxdWlldGx5ID0gVFJVRSkpDQogIGluc3RhbGwucGFja2FnZXMoImdncmVwZWwiKQ0KDQpgYGANCg0KIyMgQ2FsbGluZyByZXF1aXJlZCBwYWNrYWdlcw0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoQmlvY01hbmFnZXIpDQpsaWJyYXJ5KEdFT21ldGFkYikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGVkZ2VSKQ0KbGlicmFyeShiaW9tYVJ0KQ0KbGlicmFyeShDb21wbGV4SGVhdG1hcCkNCmxpYnJhcnkoY2lyY2xpemUpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncmVwZWwpDQpgYGANCg0KIyMgRG93bmxvYWQgdGhlIGRhdGENCiMjIyBHU0UxNTIwNzQgcmF3IGRhdGEgc3VwcGxlbWVudGFyeSBmaWxlIGRvd25sb2FkZWQNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpzZmlsZXMgPSBnZXRHRU9TdXBwRmlsZXMoJ0dTRTE1MjA3NScpDQpmbmFtZXMgPSByb3duYW1lcyhzZmlsZXMpDQojIHRoZXJlIGlzIG9ubHkgb25lIHN1cHBsZW1lbnRhbCBmaWxlDQpyZWFkRGF0YSA9IHJlYWQudGFibGUoZm5hbWVzWzFdLGhlYWRlcj1UUlVFLCBjaGVjay5uYW1lcyA9IFRSVUUpDQpgYGANCiMjIERhdGENCg0KIERhdGEgZnJvbSBbQGxpZWJlcm1hbjIwMjB2aXZvXS4NCmBgYHtyfQ0Ka2FibGUocmVhZERhdGFbMTo1LCAxOjVdLCB0eXBlID0gImh0bWwiLCByb3cubmFtZXMgPSBUUlVFKQ0KYGBgDQoNCiBUYWJsZSAxOiBPcmlnaW5hbCBkYXRhIGNvbnRhaW5zIEhHTkMgYW5ub3RhdGlvbiBhcyByb3cgbmFtZXMuIENvbHVtbiBuYW1lcyBoYXZlIHByZWZpeGVzIGJlZm9yZSB0aGVpciBpZGVudGlmaWVyIG51bWJlciBhcyBlaXRoZXIgUE9TIG9yIE5FRy4gQ29ycmVzcG9uZGluZyB0byBlaXRoZXIgcG9zaXRpdmUgZm9yIENPVklEMTkgb3IgbmVnYXRpdmUuDQoNCg0KDQojIyBBc3Nlc3MNCg0KQWRkIDEgdG8gYWxsIHZhbHVlcyBvZiBkYXRhIHNvIGxhdGVyIG9uIHdoZW4gY29uZHVjdGluZyBsb2cyKGNwbSkgd2UgY2FuIGF2b2lkIG5lZ2F0aXZlIGluZmluaXR5IHZhbHVlcy4gKEFkdmlzZWQgYnkgUHJvZmVzc29yIElzc2VybGluKQ0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpyZWFkRGF0YSA8LSByZWFkRGF0YSArIDENCmBgYA0KDQoNClNldHRpbmcgZmlyc3QgY29sdW1uIGFzIGdlbmUgaWQgZm9yIGZ1dHVyZSBmb3JtYXQgcHVycG9zZXMNCmBgYHtyfQ0KI1BsYWNlIHJvd25hbWVzIGluIGZpcnN0IGNvbHVtbiBmb3IgZnV0dXJlIGZvcm1hdCBwdXJwb3Nlcw0KaW50ZXIgPC0gZGF0YS5mcmFtZSgiSFVHTyIgPSByb3duYW1lcyhyZWFkRGF0YSkpDQpnZW5lRGF0YSA8LSBjYmluZChpbnRlciRIVUdPLCByZWFkRGF0YSkNCmNvbG5hbWVzKGdlbmVEYXRhKVsxXSA8LSAiSFVHTyINCmBgYA0KDQojIyBDbGVhbg0KUmVtb3ZlIGFueSBvdXRsaWVycyB0aGF0IGRvZXMgbm90IGhhdmUgYXQgbGVhc3QgMiByZWFkIHBlciBtaWxsaW9uIGluIG4gb2YgdGhlIHNhbXBsZXMuDQpXZSBzZXQgdGhpcyBhcyAyIHNpbmNlIHdlIGFkZCAxIHRvIGFsbCBvZiBvdXIgZGF0YXNldCBpbiB0aGUgYmVnaW5uaW5nIG9mIHRoZSBjb2RlIHRvIGhhdmUgYmV0dGVyIHBsb3RzLg0KRGVub3RpbmcgbiBhcyB0aGUgc21hbGxlc3QgZ3JvdXAgb2YgcmVwbGljYXRlcyB3aGljaCBpcyB0aGUgY29udHJvbCBncm91cCBvZiA1My4NClVzaW5nIG4gPSA1MyBjb25kdWN0IHRoZSByZW1vdmFsIG9mIGxvdyBjb3VudHMuDQpgYGB7cn0NCiN0cmFuc2xhdGUgb3V0IGNvdW50cyBpbnRvIGNvdW50cyBwZXIgbWlsbGlzb24gdXNpbmcgDQojdGhlIGVkZ2VSIHBhY2thZ2UgZnVuY3Rpb24gY3BtDQpjcG1zID0gY3BtKGdlbmVEYXRhWywyOjQ4NV0pDQpyb3duYW1lcyhjcG1zKSA8LSBnZW5lRGF0YVssMV0NCiMgZ2V0IHJpZCBvZiBsb3cgY291bnRzDQprZWVwID0gcm93U3VtcyhjcG1zID4yKSA+PTUzDQpnZW5lRGF0YV9leHBfZmlsdGVyZWQgPSBnZW5lRGF0YVtrZWVwLF0NCmBgYA0KDQpSZW1vdmUgdmVyc2lvbiBudW1iZXJzIGlmIHRoZXkgZXhpc3RzIG9uIGdlbmUgaWQoSFVHTykgY29sdW1uLg0KVGhpcyBtYWtlcyBpdCBlYXNpZXIgZm9yIG1hcHBpbmcgbGF0ZXIgb24uDQpgYGB7cn0NCmdlbmVEYXRhX2V4cF9maWx0ZXJlZFssMV0gPC0gZ3N1YigiXFwuWzAtOV0iLCAiIiwgZ2VuZURhdGFfZXhwX2ZpbHRlcmVkWywxXSkNCmBgYA0KDQojIyBNYXANCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQ0KI01hcHBpbmcgdGhlIG5hbWUgdXNpbmcgYmlvbWF0cg0KIyBsaXN0IGF2YWlsYWJsZSBnZW5lIGFubm90YXRpb24gZGF0YWJhc2VzDQpiaW8gPC0gdXNlTWFydCgiZW5zZW1ibCIsIGRhdGFzZXQgPSAiaHNhcGllbnNfZ2VuZV9lbnNlbWJsIikNCmNvbnZlcnNpb25fc3Rhc2ggPC0gImdlbmVNYXBwaW5nLnJkcyINCmlmKGZpbGUuZXhpc3RzKGNvbnZlcnNpb25fc3Rhc2gpKXsNCiAgZ2VuZU1hcHBpbmcgPC0gcmVhZFJEUyhjb252ZXJzaW9uX3N0YXNoKQ0KfSBlbHNlew0KIyBjb252ZXJ0IGNvbHVtbiBvZiBnZW5lIElEcyB0byBIdWdvIHN5bWJvbHMNCmdlbmVNYXBwaW5nIDwtIGdldEJNKGF0dHJpYnV0ZXMgPSBjKCJlbnNlbWJsX2dlbmVfaWQiLCAiaGduY19zeW1ib2wiKSwNCiAgICAgICAgICAgICAgICAgICAgIG1hcnQgPSBiaW8sDQogICAgICAgICAgICAgICAgICAgICBmaWx0ZXJzID0gImhnbmNfc3ltYm9sIiwNCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGdlbmVEYXRhX2V4cF9maWx0ZXJlZFssMV0pDQpzYXZlUkRTKGdlbmVNYXBwaW5nLCBjb252ZXJzaW9uX3N0YXNoKQ0KfQ0KYGBgDQoNCkNvbWJpbmUgdGhlIG1hcHBlZCBnZW5lIGRhdGEgdG8gb3JpZ2luYWwgZGF0YQ0KYGBge3J9DQojTWVyZ2UgdGhlIGRhdGENCm1lcmdlZERhdGEgPC0gbWVyZ2UoZ2VuZURhdGFfZXhwX2ZpbHRlcmVkLCBnZW5lTWFwcGluZywgYnkueCA9IDEsIGJ5LnkgPSAyKQ0KI3JlbW92ZSBkdXBsaWNhdGUgcm93cyBpbiB0aGUgZ2VuZSBkYXRhDQptZXJnZWREYXRhTm9EdXAgPC0gbWVyZ2VkRGF0YVshZHVwbGljYXRlZChtZXJnZWREYXRhWywxOjQ4NV0pLF0NCg0KYGBgDQoNCiMjIEFwcGx5IE5vcm1hbGl6YXRpb24NClJhbmRvbWx5IHNhbXBsZSBkYXRhIHRvIHJlZHVjZSB0aGUgc2l6ZSBvZiBzYW1wbGUuIE9yaWdpbmFsIHNhbXBsZSBpcyB0b28gbGFyZ2UNCmxlYWRpbmcgdG8gY29tcHV0YXRpb24gZXJyb3JzIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiBhdXRob3IncyBjb21wdXRlci4NCmBgYHtyfQ0KDQpzZXQuc2VlZCgxMjM0NSkNCnJhbmRvbVNhbXBsZVBPUyA8LSBzYW1wbGUobWVyZ2VkRGF0YU5vRHVwWzI6NDMxXSwgMjUpDQpyYW5kb21TYW1wbGVORUcgPC0gc2FtcGxlKG1lcmdlZERhdGFOb0R1cFs0MzI6NDg1XSwgMjUpDQpyYW5kb21TYW1wbGUgPC0gY2JpbmQocmFuZG9tU2FtcGxlUE9TLHJhbmRvbVNhbXBsZU5FRywgbWVyZ2VkRGF0YU5vRHVwJGVuc2VtYmxfZ2VuZV9pZCwgbWVyZ2VkRGF0YU5vRHVwJEhVR08pDQoNCg0KYGBgDQoNCkRlZmluZSBncm91cHMgdG8gdXNlIGluIG5vcm1hbGl6YXRpb24NCmBgYHtyfQ0KDQpzYW1wbGVzIDwtIGRhdGEuZnJhbWUobGFwcGx5KGNvbG5hbWVzKHJhbmRvbVNhbXBsZVsxOjUwXSksIA0KICAgICAgICBGVU49ZnVuY3Rpb24oeCl7dW5saXN0KHN0cnNwbGl0KHgsIA0KICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXQgPSAiXyIpKVtjKDIsMSldfSkpDQpjb2xuYW1lcyhzYW1wbGVzKSA8LSBjb2xuYW1lcyhyYW5kb21TYW1wbGVbMTo1MF0pDQpyb3duYW1lcyhzYW1wbGVzKSA8LSBjKCJwYXRpZW50cyIsImNlbGxfdHlwZSIpDQpzYW1wbGVzIDwtIGRhdGEuZnJhbWUodChzYW1wbGVzKSkNCg0KYGBgDQoNCg0KQXBwbHlpbmcgVE1NIHRvIGRhdGENCmBgYHtyfQ0KDQpmaWx0ZXJlZF9kYXRhX21hdHJpeCA8LSBhcy5tYXRyaXgocmFuZG9tU2FtcGxlWzE6NTBdKQ0Kcm93bmFtZXMoZmlsdGVyZWRfZGF0YV9tYXRyaXgpIDwtIHJhbmRvbVNhbXBsZSRgbWVyZ2VkRGF0YU5vRHVwJGVuc2VtYmxfZ2VuZV9pZGANCmQgPSBER0VMaXN0KGNvdW50cz1maWx0ZXJlZF9kYXRhX21hdHJpeCwgZ3JvdXA9c2FtcGxlcyRjZWxsX3R5cGUpDQoNCmQgPSBjYWxjTm9ybUZhY3RvcnMoZCkNCg0Kbm9ybWFsaXplZF9jb3VudHMgPC0gY3BtKGQpDQojYWRkIGNvbHVtbnMgb2YgZW5zZW1ibCBhbmQgaGduYyBpZA0KDQpub3JtYWxpemVkX2NvdW50X2RhdGEgPSBkYXRhLmZyYW1lKG5vcm1hbGl6ZWRfY291bnRzKQ0Kbm9ybWFsaXplZF9jb3VudF9kYXRhJGVuc2VtYmxfZ2VuZV9pZCA8LSBtZXJnZWREYXRhTm9EdXAkZW5zZW1ibF9nZW5lX2lkDQpub3JtYWxpemVkX2NvdW50X2RhdGEkaGduY19zeW1ib2wgPC0gbWVyZ2VkRGF0YU5vRHVwJEhVR08NCg0KDQojVGhpcyBpcyBhIGR1cGxpY2F0ZSBlbnNlbWJsIGlkIHRoYXQgaXMgZ2l2aW5nIGVycm9ycyB3aGVuIHJ1bm5pbmcgY29kZS4NCm5vcm1hbGl6ZWRfY291bnRfZGF0YSA8LSBub3JtYWxpemVkX2NvdW50X2RhdGFbLWMoMTkwMiksXQ0KYGBgDQoNCg0KYGBge3J9DQptb2RlbF9kZXNpZ24gPC0gbW9kZWwubWF0cml4KH5zYW1wbGVzJGNlbGxfdHlwZSswKQ0KZCA8LSBlc3RpbWF0ZURpc3AoZCwgbW9kZWxfZGVzaWduKQ0KYGBgDQoNCiMgRGlmZmVyZW50aWFsIEdlbmUgRXhwcmVzc2lvbg0KDQojIyBMSU1NQQ0KcC12YWx1ZSBjYWxjdWxhdGlvbiB1c2luZyBMSU1NQQ0KYGBge3J9DQptb2RlbF9kZXNpZ24gPC0gbW9kZWwubWF0cml4KH4gc2FtcGxlcyRjZWxsX3R5cGUgKQ0KYGBgDQoNCmBgYHtyfQ0KDQpleHByZXNzaW9uTWF0cml4IDwtIGFzLm1hdHJpeChub3JtYWxpemVkX2NvdW50X2RhdGFbLDE6NTBdKQ0Kcm93bmFtZXMoZXhwcmVzc2lvbk1hdHJpeCkgPC0gDQogIG5vcm1hbGl6ZWRfY291bnRfZGF0YSRlbnNlbWJsX2dlbmVfaWQNCmNvbG5hbWVzKGV4cHJlc3Npb25NYXRyaXgpIDwtIA0KICBjb2xuYW1lcyhub3JtYWxpemVkX2NvdW50X2RhdGEpWzE6NTBdDQptaW5pbWFsU2V0IDwtIEV4cHJlc3Npb25TZXQoYXNzYXlEYXRhPWV4cHJlc3Npb25NYXRyaXgpDQoNCmBgYA0KDQoNClRha2luZyBpbnRvIGFjY291bnQgUGF0aWVudCB2YXJpYWJpbGl0eQ0KYGBge3J9DQptb2RlbF9kZXNpZ25fcGF0IDwtIG1vZGVsLm1hdHJpeCgNCiAgfiBzYW1wbGVzJHBhdGllbnRzICsgc2FtcGxlcyRjZWxsX3R5cGUpDQpgYGANCg0KYGBge3J9DQpmaXRfcGF0IDwtIGxtRml0KG1pbmltYWxTZXQsIG1vZGVsX2Rlc2lnbl9wYXQpDQpgYGANCg0KDQpgYGB7cn0NCmZpdDJfcGF0IDwtIGVCYXllcyhmaXRfcGF0LHRyZW5kPVRSVUUpDQoNCnRvcGZpdF9wYXQgPC0gdG9wVGFibGUoZml0Ml9wYXQsIA0KICAgICAgICAgICAgICAgICAgIGNvZWY9bmNvbChtb2RlbF9kZXNpZ25fcGF0KSwNCiAgICAgICAgICAgICAgICAgICBhZGp1c3QubWV0aG9kID0gIkJIIiwNCiAgICAgICAgICAgICAgICAgICBudW1iZXIgPSBucm93KGV4cHJlc3Npb25NYXRyaXgpKQ0KI21lcmdlIGhnbmMgbmFtZXMgdG8gdG9wZml0IHRhYmxlDQpvdXRwdXRfaGl0c19wYXQgPC0gbWVyZ2Uobm9ybWFsaXplZF9jb3VudF9kYXRhWyw1MTo1Ml0sDQogICAgICAgICAgICAgICAgICAgICAgICAgdG9wZml0X3BhdCxieS55PTAsYnkueD0xLGFsbC55PVRSVUUpDQojc29ydCBieSBwdmFsdWUNCm91dHB1dF9oaXRzX3BhdCA8LSBvdXRwdXRfaGl0c19wYXRbb3JkZXIob3V0cHV0X2hpdHNfcGF0JFAuVmFsdWUpLF0NCmBgYA0KDQpgYGB7cn0NCmxlbmd0aCh3aGljaChvdXRwdXRfaGl0c19wYXQkUC5WYWx1ZSA8IDAuMDUpKQ0KbGVuZ3RoKHdoaWNoKG91dHB1dF9oaXRzX3BhdCRhZGouUC5WYWwgPCAwLjA1KSkNCmBgYA0KDQojIyBRTEYNCg0KYGBge3J9DQpkID0gREdFTGlzdChjb3VudHM9ZmlsdGVyZWRfZGF0YV9tYXRyaXgsIGdyb3VwPXNhbXBsZXMkY2VsbF90eXBlKQ0KYGBgDQpgYGB7cn0NCmQgPC0gZXN0aW1hdGVEaXNwKGQsIG1vZGVsX2Rlc2lnbl9wYXQpDQpgYGANCg0KYGBge3J9DQpmaXQgPC0gZ2xtUUxGaXQoZCwgbW9kZWxfZGVzaWduX3BhdCkNCmBgYA0KDQoNCmBgYHtyfQ0KcWxmLnBvc192c19uZWcgPC0gZ2xtUUxGVGVzdChmaXQsIGNvZWY9J3NhbXBsZXMkY2VsbF90eXBlUE9TJykNCmthYmxlKHRvcFRhZ3MocWxmLnBvc192c19uZWcpLCB0eXBlPSJodG1sIixyb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQpQLXZhbHVlcyB3ZXJlIGNvcnJlY3RlZCB1c2luZyBRdWFzaWxpa2VsaWhvb2QgbWV0aG9kLg0KUXVhc2lsaWtlbGlob29kIGlzIGJldHRlciBiZWNhY3VzZSBpdCBpcyB0YWlsb3JlZCB0b3dhcmRzIFJOQXNlcSBkYXRhDQoNCmBgYHtyfQ0KcWxmX291dHB1dF9oaXRzIDwtIHRvcFRhZ3MocWxmLnBvc192c19uZWcsc29ydC5ieSA9ICJQVmFsdWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbiA9IG5yb3cobm9ybWFsaXplZF9jb3VudF9kYXRhKSkNCmxlbmd0aCh3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlIDwgMC4wNSkpDQpsZW5ndGgod2hpY2gocWxmX291dHB1dF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpKQ0KYGBgDQoNCiMgVGhyZXNob2xkZWQgb3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcw0KDQojIyBXcml0ZSB0byBmaWxlIHVwcmVndWxhdGVkLCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcw0KDQpXaGljaCBvbmVzIGFyZSB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZA0KYGBge3J9DQpsZW5ndGgod2hpY2gocWxmX291dHB1dF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUgDQogICAgICAgICAgICAgJiBxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMgPiAwKSkNCg0KbGVuZ3RoKHdoaWNoKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1IA0KICAgICAgICAgICAgICYgcWxmX291dHB1dF9oaXRzJHRhYmxlJGxvZ0ZDIDwgMCkpDQpgYGANCg0KYGBge3J9DQpxbGZfb3V0cHV0X2hpdHNfd2l0aGduIDwtIG1lcmdlKHJhbmRvbVNhbXBsZVssNTE6NTJdLHFsZl9vdXRwdXRfaGl0cywgYnkueD0xLCBieS55ID0gMCkNCiNudW1iZXIgaGlnaGVyIHRoZSBsb3dlciB0aGUgcHZhbHVlLCBhbmQgaWYgaXQgaXMgdXByZWd1bGF0ZWQgbnVtYmVyIGlzIHBvc2l0aXZlLCBhbmQgbmVnYXRpdmUgZm9yIGRvd25yZWd1bGF0ZWQNCnFsZl9vdXRwdXRfaGl0c193aXRoZ25bLCJyYW5rIl0gPC0gLWxvZyhxbGZfb3V0cHV0X2hpdHNfd2l0aGduJFBWYWx1ZSxiYXNlID0xMCkgKiBzaWduKHFsZl9vdXRwdXRfaGl0c193aXRoZ24kbG9nRkMpDQpxbGZfb3V0cHV0X2hpdHNfd2l0aGduIDwtIHFsZl9vdXRwdXRfaGl0c193aXRoZ25bb3JkZXIocWxmX291dHB1dF9oaXRzX3dpdGhnbiRyYW5rKSxdDQp1cHJlZ3VsYXRlZF9nZW5lcyA8LSBxbGZfb3V0cHV0X2hpdHNfd2l0aGduJGBtZXJnZWREYXRhTm9EdXAkSFVHT2BbDQogIHdoaWNoKHFsZl9vdXRwdXRfaGl0c193aXRoZ24kUFZhbHVlIDwgMC4wNSANCiAgICAgICAgICAgICAmIHFsZl9vdXRwdXRfaGl0c193aXRoZ24kbG9nRkMgPiAwKV0NCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gcWxmX291dHB1dF9oaXRzX3dpdGhnbiRgbWVyZ2VkRGF0YU5vRHVwJEhVR09gWw0KICB3aGljaChxbGZfb3V0cHV0X2hpdHNfd2l0aGduJFBWYWx1ZSA8IDAuMDUgDQogICAgICAgICAgICAgJiBxbGZfb3V0cHV0X2hpdHNfd2l0aGduJGxvZ0ZDIDwgMCldDQp3cml0ZS50YWJsZSh4PXVwcmVndWxhdGVkX2dlbmVzLA0KICAgICAgICAgICAgZmlsZT1maWxlLnBhdGgoImRhdGEiLCJ1cHJlZ3VsYXRlZF9nZW5lcy50eHQiKSxzZXAgPSAiXHQiLA0KICAgICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UsY29sLm5hbWVzID0gRkFMU0UscXVvdGUgPSBGQUxTRSkNCndyaXRlLnRhYmxlKHg9ZG93bnJlZ3VsYXRlZF9nZW5lcywNCiAgICAgICAgICAgIGZpbGU9ZmlsZS5wYXRoKCJkYXRhIiwiZG93bnJlZ3VsYXRlZF9nZW5lcy50eHQiKSxzZXAgPSAiXHQiLA0KICAgICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UsY29sLm5hbWVzID0gRkFMU0UscXVvdGUgPSBGQUxTRSkNCndyaXRlLnRhYmxlKHg9ZGF0YS5mcmFtZShnZW5lbmFtZT0gcWxmX291dHB1dF9oaXRzX3dpdGhnbiRgbWVyZ2VkRGF0YU5vRHVwJEhVR09gLEZfc3RhdD0gcWxmX291dHB1dF9oaXRzX3dpdGhnbiRyYW5rKSwNCiAgICAgICAgICAgIGZpbGU9ZmlsZS5wYXRoKCJkYXRhIiwicmFua2VkX2dlbmVsaXN0LnR4dCIpLHNlcCA9ICJcdCIsDQogICAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSxjb2wubmFtZXMgPSBGQUxTRSxxdW90ZSA9IEZBTFNFKQ0KYGBgDQoNCiMgTm9uLXRocmVzaG9sZGVkIEdlbmUgc2V0IEVucmljaG1lbnQgQW5hbHlzaXMNCg0KYGBge3J9DQpnbXRfdXJsID0gImh0dHA6Ly9kb3dubG9hZC5iYWRlcmxhYi5vcmcvRU1fR2VuZXNldHMvY3VycmVudF9yZWxlYXNlL0h1bWFuL3N5bWJvbC8iDQojIGxpc3QgYWxsIHRoZSBmaWxlcyBvbiB0aGUgc2VydmVyDQpmaWxlbmFtZXMgPSBSQ3VybDo6Z2V0VVJMKGdtdF91cmwpDQp0YyA9IHRleHRDb25uZWN0aW9uKGZpbGVuYW1lcykNCmNvbnRlbnRzID0gcmVhZExpbmVzKHRjKQ0KY2xvc2UodGMpDQojIGdldCB0aGUgZ210IHRoYXQgaGFzIGFsbCB0aGUgcGF0aHdheXMgYW5kIGRvZXMgbm90IGluY2x1ZGUgdGVybXMgaW5mZXJyZWQNCiMgZnJvbSBlbGVjdHJvbmljIGFubm90YXRpb25zKElFQSkgc3RhcnQgd2l0aCBnbXQgZmlsZSB0aGF0IGhhcyBwYXRod2F5cyBvbmx5DQpyeCA9IGdyZWdleHByKCIoPzw9PGEgaHJlZj1cIikoLiouR09CUF9BbGxQYXRod2F5c19ub19HT19pZWEuKi4pKC5nbXQpKD89XCI+KSIsIGNvbnRlbnRzLA0KICAgIHBlcmwgPSBUUlVFKQ0KZ210X2ZpbGUgPSB1bmxpc3QocmVnbWF0Y2hlcyhjb250ZW50cywgcngpKQ0KZG93bmxvYWQuZmlsZShwYXN0ZShnbXRfdXJsLCBnbXRfZmlsZSwgc2VwID0gIiIpLCAiYmFkZXJfbGFiLmdtdCIpDQpgYGANCg0KIyMgQ29uZHVjdCBub24tdGhyZXNob2xkZWQgZ2VuZSBzZXQgZW5yaWNobWVudCBhbmFseXNpcyB1c2luZyB0aGUgcmFua2VkIHNldCBvZiBnZW5lcyBmcm9tIEFzc2lnbm1lbnQgIzIuIFwgDQoNCiMjIyAxLiBXaGF0IG1ldGhvZCBkaWQgeW91IHVzZT8gV2hhdCBnZW5lc2V0cyBkaWQgeW91IHVzZT8gTWFrZSBzdXJlIHRvIHNwZWNpZnkgdmVyc2lvbnMgYW5kIGNpdGUgeW91ciBtZXRob2RzLiBcIA0KSSB1c2VkIHRoZSBHU0VBIGRlc2t0b3AgYXBwbGljYXRpb24gdG8gcnVuIEdTRUEgW0Bnc2VhMV0uICANCkkgdXNlZCB0aGUgZ2VuZXNldHMgZnJvbSB0aGUgYmFkZXIgbGFiIGV4dHJhY3RlZCBmcm9tIHRoZSBjb2RlIGFib3ZlIEkgdXNlZC4gT3IgaXQgY2FuIGJlIHJldHJpZXZlZCBmcm9tIGhlcmUgaHR0cDovL2Rvd25sb2FkLmJhZGVybGFiLm9yZy9FTV9HZW5lc2V0cy9jdXJyZW50X3JlbGVhc2UvSHVtYW4vc3ltYm9sLy4gIA0KDQojIyMgMi4gU3VtbWFyaXplIHlvdXIgZW5yaWNobWVudCByZXN1bHRzLlwgDQpTQVJzLUNvVi0yIHBvc2l0aXZlIHNhbXBsZXM6ICANCjQ5NjUgLyA2MDc0IGdlbmUgc2V0cyBhcmUgdXByZWd1bGF0ZWQgaW4gcGhlbm90eXBlIG5hX3BvcyAgDQo0NDIgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudCBhdCBGRFIgPCAyNSUgIA0KNDEwIGdlbmUgc2V0cyBhcmUgc2lnbmlmaWNhbnRseSBlbnJpY2hlZCBhdCBub21pbmFsIHB2YWx1ZSA8IDElICANCjY2MiBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50bHkgZW5yaWNoZWQgYXQgbm9taW5hbCBwdmFsdWUgPCA1JSAgDQpUb3AgZ2VuZS1zZXQ6IEhBTExNQVJLX0lOVEVSRkVST05fQUxQSEFfUkVTUE9OU0UlTVNJR0RCSEFMTE1BUkslSEFMTE1BUktfSU5URVJGRVJPTl9BTFBIQV9SRVNQT05TRSAgDQpOdW1iZXIgb2YgZ2VuZXMgaW4gbGVhZGluZyBlZGdlOiA4MCAgDQpUb3AgZ2VuZSBhc3NvY2lhdGVkOiBDWENMMTEgIA0KDQpTQVJzLUNvVi0yIG5lZ2F0aXZlIHNhbXBsZXM6ICANCjExMDkgLyA2MDc0IGdlbmUgc2V0cyBhcmUgdXByZWd1bGF0ZWQgaW4gcGhlbm90eXBlIG5hX25lZyAgDQoyNzQgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IEZEUiA8IDI1JSAgDQoxOTYgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IG5vbWluYWwgcHZhbHVlIDwgMSUgIA0KMjc2IGdlbmUgc2V0cyBhcmUgc2lnbmlmaWNhbnRseSBlbnJpY2hlZCBhdCBub21pbmFsIHB2YWx1ZSA8IDUlICANClRvcCBnZW5lLXNldDogRU5FUkdZIERFUklWQVRJT04gQlkgT1hJREFUSU9OIE9GIE9SR0FOSUMgQ09NUE9VTkRTJUdPQlAlR086MDAxNTk4MCAgDQpOdW1iZXIgb2YgZ2VuZXMgaW4gbGVhZGluZyBlZGdlOiAxNjUgIA0KVG9wIGdlbmUgYXNzb2NpYXRlZDogVEVGTSAgDQoNCiMjIyAzLiBIb3cgZG8gdGhlc2UgcmVzdWx0cyBjb21wYXJlIHRvIHRoZSByZXN1bHRzIGZyb20gdGhlIHRocmVzaG9sZGVkIGFuYWx5c2lzIGluIEFzc2lnbm1lbnQgIzIuIENvbXBhcmUgcXVhbGl0YXRpdmVseS4gSXMgdGhpcyBhIHN0cmFpZ2h0IGZvcndhcmQgY29tcGFyaXNvbj8gV2h5IG9yIHdoeSBub3Q/IFwgDQpGb3IgdGhlIHVwcmVndWxhdGVkIGdlbmVzIHRoZSB0b3AgcmVzdWx0cyBhcmUgbmVnYXRpdmUgcmVndWxhdGlvbiBvZiB2aXJhbCBnZW5vbWUgcmVwbGljYXRpb24sIG5lZ2F0aXZlIHJlZ3VsYXRpb24gb2YgdmlyYWwgcHJvY2VzcywgcmVzcG9uc2UgdG8gdHlwZSBJSSBpbnRlcmZlcm9uLiBkb3ducmVndWxhdGVkIHdlIGdvdCBjeXRvcGxhc21pYyB0cmFuc2xhdGlvbiwgcG9zaXRpdmUgcmVndWxhdGlvbiBvZiByZXNwaXJhdG9yeSBidXJzdCwgYW5kIGludGVybWVkaWF0ZSBmaWxhbWVudC1iYXNlZCBwcm9jZXNzLiBGb3IgdXByZWd1bGF0ZWQgaW4gdGhyZXNob2xkZWQgYW5kIG5vbi10aHJlc2hvbGRlZCB0aGV5IGFsaWduIGEgYml0IHRvZ2V0aGVyIGJ5IGhhdmluZyBpbnRlcmZlcm9uIHJlbGF0ZWQgcGF0aHdheSByZXN1bHRzLiBPdGhlciB0aGVuIHRoYXQgdGhleSBkb24ndCBzZWVtIHRvIGJlIHNpbWlsYXIuIEEgY29tbW9uIHBhdGh3YXkgaW4gZG93bnJlZ3VsYXRlZCBhbmQgYW5kIGFsbCBvZiB0aGUgZ2VuZXMgZm9yIHRocmVzaG9sZGVkIHdhcyBhIHBhdGh3YXkgcmVsYXRlZCB0byBjeXRvcGxhc21pYy4gSG93ZXZlciBpbiBub24gdGhyZXNob2xkZWQgdGhlcmUgd2VyZSBjeXRvcGxhc21pYyByZWxhdGVkIHBhdGh3YXlzIGJ1dCB3ZXJlIHZlcnkgbG93IGluIHRoZSBsaXN0LiBJdCBpcyBub3QgYSBzdHJhaWdodCBmb3J3YXJkIGNvbXBhcmlzb24gdGhleSBib3RoIGhhdmUgZGlmZmVyZW50IHZhbHVlcyBhcyBhbmFseXNpcy4gVGhlIHRocmVzaG9sZGVkIGNvdWxkIGJlIG1vcmUgc2Vuc2l0aXZlIHdoaWxlIHRoZSBub24tdGhyZXNob2xkZWQgYmUgbW9yZSBnZW5lcmFsLiAgDQoNCg0KDQoNCiMgVmlzdWFsaXplIHlvdXIgZ2VuZSBzZXQgRW5yaWNobWVudCBBbmFseXNpcyBpbiBDeXRvc2NhcGUgXCANCg0KDQojIyMgMS4gXCAgDQojIyMgQ3JlYXRlIGFuIGVucmljaG1lbnQgbWFwIC0gaG93IG1hbnkgbm9kZXMgYW5kIGhvdyBtYW55IGVkZ2VzIGluIHRoZSByZXN1bHRpbmcgbWFwPyBcIA0KMzc5IE5vZGVzICANCjE1MTEgRWRnZXMgICANCg0KIyMjIFdoYXQgdGhyZXNob2xkcyB3ZXJlIHVzZWQgdG8gY3JlYXRlIHRoaXMgbWFwPw0KRkRSIHEtdmFsdWUgY3V0b2ZmOiAwLjEgIA0KQW5hbHlzaXMgVHlwZTogR1NFQSAgDQpOb2RlIGN1dG9mZjogMC4xICANCkVkZ2UgY3V0b2ZmOiAwLjM3NSAgIA0KDQojIyMgTWFrZSBzdXJlIHRvIHJlY29yZCBhbGwgdGhyZXNob2xkcy4gSW5jbHVkZSBhIHNjcmVlbnNob3Qgb2YgeW91ciBuZXR3b3JrIHByaW9yIHRvIG1hbnVhbCBsYXlvdXQuIFwgDQoNCiAhW0ZpZ3VyZSAwOiBTY3JlZW5zaG90IG9mIG5ldHdvcmsgcHJpb3IgdG8gbWFudWFsIGxheW91dF0oLi9maWd1cmUvcHJpb3J0b21hbnVhbC5wbmcpDQoNCiMjIyAyLiBBbm5vdGF0ZSB5b3VyIG5ldHdvcmsgLSB3aGF0IHBhcmFtZXRlcnMgZGlkIHlvdSB1c2UgdG8gYW5ub3RhdGUgdGhlIG5ldHdvcmsuIElmIHlvdSBhcmUgdXNpbmcgdGhlIGRlZmF1bHQgcGFyYW1ldGVycyBtYWtlIHN1cmUgdG8gbGlzdCB0aGVtIGFzIHdlbGwuICANClVzZWQgdGhlIGF1dG8gYW5ub3RhdGUgYXBwbGljYXRpb24gaW4gY3l0b3NjYXBlLiAgDQpDbHVzdGVyIGFsZ29yaXRobTogTUNMIENsdXN0ZXIgIA0KTGFiZWwgQ29sdW1uOiBHU19ERVNDUiAgDQpMYWJlbCBBbGdvcml0aG06IFdvcmRDbG91ZDogQWRqYWNlbnQgV29yZHMoZGVmYXVsdCkgICANCk1heCB3b3JkcyBwZXIgbGFiZWw6IDMgIA0KTWluaW11bSB3b3JkIG9jY3VycmVuY2U6IDEgICANCkFkamFjZW50IHdvcmQgYm9udXM6IDggIA0KQm9yZGVyIFdpZHRoOiAzICANCk9wYWNpdHk6IDIwJSAgDQpGb250IFNjYWxlOiAyMCUgICANCg0KDQogIVtGaWd1cmUgMTogQW5ub3RhdGVkIG5ldHdvcmtdKC4vZmlndXJlL2Fubm90YXRlZG5ldHdvcmsucG5nKQ0KDQojIyMgMy4gTWFrZSBhIHB1YmxpY2F0aW9uIHJlYWR5IGZpZ3VyZSAtIGluY2x1ZGUgdGhpcyBmaWd1cmUgd2l0aCBwcm9wZXIgbGVnZW5kcyBpbiB5b3VyIG5vdGVib29rLiAgDQoNCiAhW0ZpZ3VyZSAyOiBDb2xsYXBzZWRdKC4vZmlndXJlL3B1YmxpY2F0aW9ucmVhZHkucG5nKQ0KIA0KIyMjIDQuIENvbGxhcHNlIHlvdXIgbmV0d29yayB0byBhIHRoZW1lIG5ldHdvcmsuIFdoYXQgYXJlIHRoZSBtYWpvciB0aGVtZXMgcHJlc2VudCBpbiB0aGlzIGFuYWx5c2lzPyBEbyB0aGV5IGZpdCB3aXRoIHRoZSBtb2RlbD8gQXJlIHRoZXJlIGFueSBub3ZlbCBwYXRod2F5cyBvciB0aGVtZXM/IFwgDQoNCiAhW0ZpZ3VyZSAzOiBDb2xsYXBzZWRdKC4vZmlndXJlL2NvbGxhcHNlZC5wbmcpDQpNYWpvciB0aGVtZXMgcHJlc2VudDogIA0KDQpVcC1yZWd1bGF0ZWQ6ICANCg0KLSBHUENSUyBSaG9kb3BzaW4gbGlnYW5kICANCi0gQ2hlbW9raW5lIE1pZ3JhdGlvbiBjaGVtb3RheGlzICAgDQotIENlbGx1bGFyIHJlc3BvbnNlIG5lY3Jvc2lzICAgDQotIHR5cGUgSUkgaW50ZXJmZXJvbiAgIA0KLSBNaWdyYXRpb24gbW9ub2N5dGUgY2hlbW90YXhpcyAgICANCi0gU3VyZmFjZSByZWNlcHRvciBwYXR0ZXJuICAgDQoNCkRvd24tcmVndWxhdGVkOiAgDQoNCi0gZ2x1Y29uZW9nZW5lc2lzIGdseWNvbHlzaXMgICAgDQotIHN1cGVycGF0aHdheSB3YXJidXJnIGVmZmVjdCAgICANCi0gc3JwIHByb3RlaW4gc3ludGhlc2lzICANCg0KRG8gdGhleSBmaXQgd2l0aCB0aGUgbW9kZWw/ICAgDQoNClRoZXJlIGFyZSBtYWpvciB0aGVtZXMgdGhhdCBjb2luY2lkZSB3aXRoIHRoZSBtb2RlbCBwcmVzZW50IGluIHRoZSBvcmlnaW5hbCBwYXBlci4gU3VjaCBhcyB0aGUgdHlwZSBJSSBpbnRlcmZlcm9uLCBvciBzdXJmYWNlIHJlY2VwdG9yIHBhdHRlcm4gaXMgc29tZXRoaW5nIHRoYXQgaXMgY29tbW9uIGluIENPVklELTE5LiAgDQoNCk5vdmVsIHBhdGh3YXlzPyAgIA0KVGhlcmUgZXhpc3RzIHNvbWUgbm92ZWwgcGF0aHdheXMgaW4gdGhlIG5ldHdvcmsgc3VjaCBhcyB0aGUgZm94by1tZWRpYXRlZCB0cmFuc2NyaXB0aW9uIG9mIGNlbGwgY3ljbGUgZ2VuZS4gUGF0aHdheXMgc3VjaCBhcyB0aGVzZSB0aGVyZSBhcmUgbm90IGEgbG90IG9mIHN0dWRpZXMgb24gdGhlbS4gTm90IGp1c3QgdGhpcyBvbmUgYnV0IG91dCBvZiB0aGUgbWFueSBwYXRod2F5cyB0aGVyZSBhcmUgc29tZSBub3ZlbCBpbnRlcmVzdGluZyBwYXRod2F5cyB0byBsb29rIGF0LiAgIA0KDQoNCiMgSW50ZXJwcmV0YXRpb24gYW5kIGRldGFpbGVkIHZpZXcgb2YgcmVzdWx0cyANCg0KVGhlIG1vc3QgaW1wb3J0YW50IGFzcGVjdCBvZiB0aGUgYW5hbHlzaXMgaXMgcmVsYXRpbmcgeW91ciByZXN1bHRzIGJhY2sgdG8gdGhlIGluaXRpYWwgZGF0YSBhbmQgcXVlc3Rpb24uICANCg0KIyMjIDEuIERvIHRoZSBlbnJpY2htZW50IHJlc3VsdHMgc3VwcG9ydCBjb25jbHVzaW9ucyBvciBtZWNoYW5pc20gZGlzY3Vzc2VkIGluIHRoZSBvcmlnaW5hbCBwYXBlcj8gSG93IGRvIHRoZXNlIHJlc3VsdHMgZGlmZmVyIGZyb20gdGhlIHJlc3VsdHMgeW91IGdvdCBmcm9tIEFzc2lnbm1lbnQgIzIgdGhyZXNob2xkZWQgbWV0aG9kcy4NCg0KVGhpcyBpcyBhIHF1b3RhdGlvbiB0YWtlbiBmcm9tIHRoZSBvcmlnaW5hbCBwYXBlciAiU0FSUy1Db1YtMiBpbmR1Y2VkIGEgc3Ryb25nIGFudGl2aXJhbCByZXNwb25zZSB3aXRoIHVwLXJlZ3VsYXRpb24gb2YgYW50aXZpcmFsIGZhY3RvcnMgc3VjaCBhcyBPQVMxLTMgYW5kIElGSVQxLTMgYW5kIFQgaGVscGVyIHR5cGUgMSAoVGgxKSBjaGVtb2tpbmVzIENYQ0w5LzEwLzExLCBhcyB3ZWxsIGFzIGEgcmVkdWN0aW9uIGluIHRyYW5zY3JpcHRpb24gb2Ygcmlib3NvbWFsIHByb3RlaW5zIiBbQGxpZWJlcm1hbjIwMjB2aXZvXS4gVGhleSBoYXZlIGZvdW5kIHVwLXJlZ3VsYXRpb24gaW4gbnVtYmVyIG9mIGdlbmVzLiBUaGUgbGFyZ2VzdCBjb2xsYXBzZWQgdGhlbWUgd2l0aCA3MjkgZ2VuZXMgdGhlIEdQQ1JTIFJob2RvcHNpbiBsaWdhbmQgaGFzIHR3byB2ZXJ5IGxhcmdlIHBhdGh3YXlzIG5hbWVkIHRoZSBHUENSIGxpZ2FuZCBiaW5kaW5nLCBhbmQgdGhlIENMQVNTIEEgMSAoUkhPRE9QU0lOLUxJS0UgUkVDRVBUT1JTKS4gQm90aCBvZiB0aGVzZSBnZW5lLXNldHMgaGF2ZSBhdCB0aGUgdG9wIG9mIHRoZWlyIGxlYWRpbmcgZWRnZSB0aGUgQ1hDTCAxMC8xMS8xMyBzaW1pbGFyIHRvIHRoZSBwYXBlciB3aGVyZSB0aGV5IGhhZCB1cC1yZWd1bGF0aW9uIGluIHRoZSBDWENMIDkvMTAvMTEuIEluIHRoaXMgc2Vuc2UgdGhlIGVucmljaG1lbnQgcmVzdWx0cyBzdXBwb3J0IGNvbmNsdXNpb25zIG1hZGUgaW4gdGhlIG9yaWdpbmFsIHBhcGVyLiBBbm90aGVyIGV4YW1wbGUgaXMgdGhlIGNoZW1va2luZSBtaWdyYXRpb24gY2hlbW90YXhpcy4gSW4gdGhpcyBtYWpvciB0aGVtZSB0aGVyZSBhcmUgZ2VuZS1zZXRzIGludm9sdmVkIGluIHBhdGh3YXlzIHN1Y2ggYXMgdGhlIHJlc3BvbnNlIHRvIHR5cGUgSUkgaW50ZXJmZXJvbiwgY2VsbHVsYXIgcmVzcG9uc2UgdG8gdHlwZSBJSSBpbnRlcmZlcm9uLCAuIEluIHRoZSBvcmlnaW5hbCBwYXBlciB0aGV5IG1lbnRpb24gdGhhdCBhcyB2aXJhbCBsb2FkIGluY3JlYXNlZCB0aGUgZXhwcmVzc2lvbiBvZiBpbnRlcmZlcm9uLXJlc3BvbnNpdmUgZ2VuZXMgd2VudCB1cC4gQm90aCBvZiB0aGUgdHdvIHRoZW1lcyBtZW50aW9uZWQgYXJlIHVwLXJlZ3VsYXRlZCBnZW5lLXNldHMuIEl0IHNlZW1zIHRoYXQgdGhlIGVucmljaG1lbnQgcmVzdWx0cyBzdXBwb3J0IHRoZSBjb25jbHVzaW9uIGluIHRoZSBvcmlnaW5hbCBwYXBlci4gIA0KQ29tcGFyaW5nIGZyb20gQTIgdGhyZXNob2xkIG1ldGhvZHMgaW4gdGhlIHVwcmVndWxhdGVkIGFuYWx5c2lzIHVzaW5nIGc6cHJvZmlsZXIgd2UgYWxzbyBoYWQgcmVzdWx0cyBzdWNoIGFzIHJlc3BvbnNlIHRvIHR5cGUgSUkgaW50ZXJmZXJvbiwgYW5kIGNlbGx1bGFyIHJlc3BvbnNlIHRvIHR5cGUgSUkgaW50ZXJmZXJvbi4gVGhpcyBhbGlnbnMgd2l0aCBvdXIgR1NFQSByZXN1bHRzLiBUaGUgc2lnbmlmaWNhbnQgcGF0aHdheXMgc2VlbSB0byBiZSBhbGlnbmluZyBidXQgdGhlIG1pbm9yIG9uZXMgdGhhdCBoYXZlIHdlYWsgc2lnbmlmaWNhbmNlIGlzIHdoZXJlIHRoZSBtYWpvciBkaWZmZXJlbmNlcyBhcmUgYmV0d2VlZW4gdCBoZSBBc3NpZ25tZW50IDIgdGhyZXNob2xkZWQgbWV0aG9kcyBhbmQgQXNzaWdubWVudCAzLiAgDQoNCkZvciBkb3duIHJlZ3VsYXRlZCBnZW5lLXNldHMgZm9yIG91ciBuZXR3b3JrIHJlc3VsdHMgZnJvbSBHU0VBIHNob3dzIGEgbWFqb3IgdGhlbWUgY2FsbGVkIHNycCBwcm90ZWluIHN5bnRoZXNpcy4gSW4gdGhpcyB3ZSBoYXZlIGdlbmVzZXRzIHN1Y2ggYXMgdGhlIGN5dG9wbGFzbWljIHRyYW5zbGF0aW9uLiBUaGlzIGdlbmUtc2V0IGlzIHRoZSBsYXJnZXN0IGdlbmUtc2V0IGluc2lkZSBzcnAgcHJvdGVpbiBzeW50aGVzaXMgYW5kIGl0IGlzIGFsc28gdGhlIHRvcCByZXN1bHQgZm9yIGRvd24gcmVndWxhdGVkIGdlbmVzIGdlbmUtc2V0IGZvciBnOnByb2ZpbGVyIHVzaW5nIEdPIGFubm90YXRpb24uICANCg0KQ29tcGFyaW5nIHRoZSBtb2RlbCBpbiBvcmlnaW5hbCBwYXBlciwgQXNzaWdubWVudCAyIHJlc3VsdHMsIGFuZCBBc3NpZ25tZW50IDMgcmVzdWx0cyB0aGUgc2lnbmlmaWNhbnQgcGF0aHdheXMgY29pbmNpZGUgYnV0IHRoZSBsZXNzIHNpZ25pZmljYW50IHBhdGh3YXlzIGlzIHdoZXJlIHRoZSBjaGFuZ2Ugb2NjdXJzLiAgDQoNCg0KDQojIyMgMi4gQ2FuIHlvdSBmaW5kIGV2aWRlbmNlLCBpLmUuIHB1YmxpY2F0aW9ucywgdG8gc3VwcG9ydCBzb21lIG9mIHRoZSByZXN1bHRzIHRoYXQgeW91IHNlZS4gSG93IGRvZXMgdGhpcyBldmlkZW5jZSBzdXBwb3J0IHlvdXIgcmVzdWx0PyANCkluIGEgcGFwZXIgdGhleSBzdGF0ZSB0aGF0IFNBUlMtQ29WLTIgaW5mZWN0ZWQgdGh5cm9pZCBnbGFuZCBhY3RpdmF0ZWQgdGhlIGludGVyZmVyb24gcGF0aHdheXMgYWxpZ25pbmcgd2l0aCBvdXIgcmVzdWx0cyBpbiB0aGUgdXAtcmVndWxhdGlvbiBbQGludGVyZmVyb25dLiBBbm90aGVyIHBhcGVyIGV4cGxhaW5zIHRoZSBkb3duIHJlZ3VsYXRpb24gb2YgY3l0b3BsYXNtaWMgdHJhbnNsYXRpb24uIFNBUlMtQ29WLTIgc3VwcHJlc3NlcyBob3N0IHByb3RlaW4gdHJhbnNsYXRpb24gbGVhZGluZyB0byBhIGRvd24gcmVndWxhdGlvbiBvZiBjeXRvcGxhc21pYyB0cmFuc2xhdGlvbiBwYXRod2F5cyBbQGN5dG9wbGFzbWljXS4gSW4gYm90aCBwYXBlcnMgd2UgY2FuIHNlZSBzdXBwb3J0aW5nIGV2aWRlbmNlIGZvciB0aGUgcmVzdWx0cyB3ZSBnb3QgZnJvbSB0aGUgR1NFQSBpbiB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZC4gDQoNCiMjIyAxLiBBZGQgYSBwb3N0IGFuYWx5c2lzIHRvIHlvdXIgbWFpbiBuZXR3b3JrIHVzaW5nIHNwZWNpZmljIHRyYW5zY3JpcHRpb24gZmFjdG9ycywgbWljcm9STkFzIG9yIGRydWdzLiBJbmNsdWRlIHRoZSByZWFzb24gd2h5IHlvdSBjaG9zZSB0aGUgc3BlY2lmaWMgbWlScywgVEZzIG9yIGRydWdzIChpLmUgcHVibGljYXRpb25zIGluZGljYXRpbmcgdGhhdCB0aGV5IG1pZ2h0IGJlIHJlbGF0ZWQgdG8geW91ciBtb2RlbCkuIFdoYXQgZG9lcyB0aGlzIHBvc3QgYW5hbHlzaXMgc2hvdz8gDQpBZGRlZCBhIGdlbmVzZXQgZm9yIGRydWdzIGZyb20gdGhlIGJhZGVyIGxhYi4gRnJvbSB0aGlzIGxpbmsgKGh0dHA6Ly9kb3dubG9hZC5iYWRlcmxhYi5vcmcvRU1fR2VuZXNldHMvY3VycmVudF9yZWxlYXNlL0h1bWFuL3N5bWJvbC9EcnVnVGFyZ2V0cy9IdW1hbl9EcnVnQmFua19hbGxfc3ltYm9sLmdtdCkuICANCg0KSSBjaG9zZSBkcnVncyBiZWNhdXNlIENPVklELTE5IGFzIG9mIDIwMjMgaGFzIG5vIGV4YWN0IGN1cmUgZm9yIHRoZSBkaXNlYXNlIHNpbmNlIHRoZSB2aXJ1cyBpcyBjb25zdGFudGx5IGV2b2x2aW5nLiBIb3dldmVyIGhhdmluZyBkcnVnIHRhcmdldHMsIGFuZCBkcnVncyB0byB0cmVhdCBDT1ZJRC0xOSBjb3VsZCBiZSBhIHZlcnkgZWZmZWN0aXZlIHdheSBvZiBkZWZlYXRpbmcgdGhlIHZpcnVzIGlmIHdlIGNhbiByZWR1Y2UgdGhlIHJpc2tzIG9mIHNldmVyaXR5IGluIENPVklELTE5LiAgDQoNCkNvbmR1Y3RlZCBhIGV4cGxvcmF0b3J5IGFuYWx5c2lzLCBhbmQga25vd24gc2lnbmF0dXJlIGFuYWx5c2lzLiAgDQpUaGUgZXhwbG9yYXRvcnkgYW5hbHlzaXMgc2hvd2VkIG1lIHRoZSBzaWduaWZpY2FudCBnZW5lc2V0cyBhbmQgdGhlc2UgYXJlIHRoZSBvbmVzIEkgY2hvc2UgdG8gZm9jdXMgb24uICANCk1hbm4tV2hpdG5leShUd28tc2lkZWQpOiAwLjA1ICANCg0KVGhlIG1vc3Qgc2lnbmlmaWNhbnQgZHJ1ZyB0YXJnZXRzIHdlcmUgQXJ0ZW5pbW9sLCBBbmlzb215Y2luLCAoUyktMy1QaGVueWxsYWN0aWMgQWNpZCwgUHVyb215Y2luLCBOQURILiAgDQoNClVzaW5nIHRoZSBPdmVybGFwIGlzIFggcGVyY2VudCBvZiBTaWcgZ3M6IGxhcmdlc3Qgb3ZlcmxhcCBkcnVnIHRhcmdldHMgaXMgTkFESCwgQXJpcGlwcmF6b2xlLCBMb3hhcGluZSwgWmlwcmFzaWRvbmUsIEFyaXBpcHJhem9sZSBMYXVyb3hpbCAgDQoNCkh5cGVyZ2VvbWV0cmljIFRlc3Q6IDAuMjUgVGhlIGJlc3QgdGVzdCB2YWx1ZXMgYXJlIE5BREgsIEFyaXBpcHJhem9sZSwgTG94YXBpbmUsIFppcHJhc2lkb25lLCBDWVQ5OTcgICANCg0KSW4gYWxsIDMgYW5hbHlzaXMgd2Ugc2VlIHRoYXQgTkFESCBpcyBleGlzdGVudC4gTkFESCBpcyB0aGUgcmVkdWNlZCBmb3JtIG9mIE5BRCsuIEluIHRoZSBkcnVnYmFuayBzeXN0ZW0gdGhleSBzYXkgdGhhdCBOQURIIGhhcyBiZWVuIHVzZWZ1bCBpbiB0cmVhdGluZyBQYXJpa2luc29uJ3MgZGlzZWFzZS4gTkFESCBpcyBhIHNpZ25pZmljYW50IG51dHJpZW50IGluIG90aGVyIGRpc2Vhc2VzIGJ1dCBob3cgYWJvdXQgZm9yIENPVklELTE5LiBNdWx0aXBsZSBwYXBlcnMgc2hvd3MgdGhhdCBOQUQrIGRlZmljaWVuY3kgbWlnaHQgYmUgb25lIG9mIHRoZSBtYWluIGNhdXNlcyBvZiB0aGUgZGlzZWFzZSBzZXZlcml0eSBpbiBDT1ZJRC0xOSBbQG5hZGhdLiBUaGlzIGFsaWducyB3aXRoIHRoZSBzaWduaWZpY2FudCBnZW5lIHNldHMgdGhhdCBhcmUgc2VlbiBpbiB0aGUgY3l0b3NjYXBlIGFuYWx5c2lzLiAgIA0KDQoNCiAhW0ZpZ3VyZSA0OiBEcnVnIFRhcmdldHNdKC4vZmlndXJlL2RydWcucG5nKQ0KVGhlIGZpZ3VyZSBpcyB0b28gbGFyZ2Ugc28gbm9uZSBvZiB0aGUgbm9kZXMgYXJlIGFjdHVhbGx5IHZpc2libGUgaW4gY3l0b3NjYXBlIHVubGVzcyB6b29tZWQgaW4uXCANClNpbmNlIGl0IGlzIGRpZmZpY3VsdCB0byB2aWV3IGluIG5ldHdvcmsgdmlldy4gSGVyZSBhcmUgdGhlIHRhYmxlIHZpZXdzIGFuZCBqdXN0IGEgZmV3IGRydWcgdGFyZ2V0cyB6b29tZWQgaW4gZm9yIHRoZSBhbmFseXNpcyBkb25lLiBcIA0KDQogIVtGaWd1cmUgNTogRHJ1ZyBUYXJnZXRzIHpvb21lZCBpbiBNYW5uLVdoaXRuZXkgbmV0d29ya10oLi9maWd1cmUvbWFubm5ldHdvcmsucG5nKQ0KIA0KIA0KIA0KICFbRmlndXJlIDY6IERydWcgVGFyZ2V0cyBNYW5uLVdoaXRuZXkgdGFibGUgdmlld10oLi9maWd1cmUvbWFubi5wbmcpDQogDQogIVtGaWd1cmUgNzogRHJ1ZyBUYXJnZXRzIHpvb21lZCBpbiBoeXBlcmdlb21ldHJpY10oLi9maWd1cmUvaHlwZXJuZXR3b3JrLnBuZykNCiAhW0ZpZ3VyZSA4OiBEcnVnIFRhcmdldHMgdGFibGUgaHlwZXJnZW9tZXRyaWNdKC4vZmlndXJlL2h5cGVyZ2VvbWV0cmljLnBuZykNCiANCiAhW0ZpZ3VyZSA5OiBEcnVnIFRhcmdldHMgem9vbWVkIGluIG92ZXJsYXBdKC4vZmlndXJlL292ZXJsYXBuZXR3b3JrLnBuZykNCiANCiANCiAhW0ZpZ3VyZSAxMDogRHJ1ZyBUYXJnZXRzIHRhYmxlIG92ZXJsYXBdKC4vZmlndXJlL292ZXJsYXAucG5nKQ0KIA0KDQojIENvbXBpbGF0aW9uDQoNClRoaXMgY29kZSBjb21waWxlcyB3aXRoIGRvY2tlciBhcyBvZiAwNC8wNC8yMDIzLiANCg0KIyBSZWZlcmVuY2VzIA==